﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using ReportWizard.Helpers;

namespace ReportWizard.DataAccess
{
    public enum HistoryEvent
    {
        Login,
        LoginFailed,
        Logout,
        Error,
        ReportCreate,
        PathChange,
        ProfileUpdate,
        PasswordUpdate,
        UserAdd,
        UserChange,
        UserRemove,
        TemlateAdd,
        TemplateChange,
        TemplateRemove,
        SelectObjectAdd,
        SelectOjectRemove,
        PerferenceValueSet,
        BookmarkAdd,
        BookmarkChange,
        BookmarkRemove
    }

    public class HistoryRecord
    {
        public int Id { get; private set; }
        public int UserId { get; private set; }
        public string Login { get; private set; }
        public HistoryEvent Action { get; set; }
        public string Description { get; set; }
        public DateTime DateCreated { get; private set; }

        public enum SortingFields
        {
            Login,
            Action,
            Description,
            DateCreated
        }

        public void Insert(int userId = 0)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand saveCmd = new SqlCommand("HistoryInsert", con);
                    saveCmd.CommandType = CommandType.StoredProcedure;

                    object objUserId = Globals.CurrentUser == null ? (object)DBNull.Value : (userId == 0 ? Globals.CurrentUser.Id : userId);

                    saveCmd.Parameters.Add("@UserId", SqlDbType.Int).Value = objUserId;
                    saveCmd.Parameters.Add("@Action", SqlDbType.VarBinary).Value = Crypto.Encrypt(Action);
                    saveCmd.Parameters.Add("@Description", SqlDbType.VarBinary).Value = Crypto.Encrypt(Description);
                    saveCmd.Parameters.Add("@Id", SqlDbType.Int).Direction = ParameterDirection.Output;

                    con.Open();
                    if (saveCmd.ExecuteNonQuery() != 0)
                    {
                        Id = Convert.ToInt32(saveCmd.Parameters["@Id"].Value);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
            }
        }

        public bool Clear(int startId, int endId)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand delCmd = new SqlCommand("HistoryClear", con);
                    delCmd.CommandType = CommandType.StoredProcedure;

                    delCmd.Parameters.Add("@StartId", SqlDbType.Int).Value = startId;
                    delCmd.Parameters.Add("@EndId", SqlDbType.Int).Value = endId;

                    con.Open();
                    return delCmd.ExecuteNonQuery() != 0;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return false;
            }
        }

        public static DateTime SelectDate(int userId, bool isMaxDate)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand getCmd = new SqlCommand
                                            {
                                                Connection = con,
                                                CommandText = isMaxDate ? "HistorySelectMaxDate" : "HistorySelectMinDate",
                                                CommandType = CommandType.StoredProcedure
                                            };

                    getCmd.Parameters.Add("@UserId", SqlDbType.Int).Value = userId;

                    con.Open();
                    object selectedDate = getCmd.ExecuteScalar();

                    return selectedDate != DBNull.Value ? Convert.ToDateTime(getCmd.ExecuteScalar()) : DateTime.Now;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return DateTime.Now;
            }
        }

        public static List<HistoryRecord> Select(int userId, DateTime startDate, DateTime endDate)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand getCmd = new SqlCommand("HistorySelectRange", con);
                    getCmd.CommandType = CommandType.StoredProcedure;

                    getCmd.Parameters.Add("@UserId", SqlDbType.Int).Value = userId;
                    getCmd.Parameters.Add("@StartDate", SqlDbType.DateTime).Value = startDate;
                    getCmd.Parameters.Add("@EndDate", SqlDbType.DateTime).Value = endDate;

                    con.Open();
                    return MapFrom(getCmd.ExecuteReader());
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        private static List<HistoryRecord> MapFrom(SqlDataReader dr)
        {
            try
            {
                if (dr != null && dr.HasRows)
                {
                    List<HistoryRecord> acList = new List<HistoryRecord>();
                    while (dr.Read())
                    {
                        HistoryRecord historyRecord = new HistoryRecord
                        {
                            Id = Convert.ToInt32(dr["Id"]),
                            UserId = dr["UserId"] != DBNull.Value ? Convert.ToInt32(dr["UserId"]) : 0,
                            Login = dr["Login"] != DBNull.Value ? Crypto.Decrypt((byte[])dr["Login"]) : "Система",
                            Action = (HistoryEvent)Enum.Parse(typeof(HistoryEvent), Crypto.Decrypt((byte[])dr["Action"])),
                            Description = Crypto.Decrypt((byte[])dr["Description"]),
                            DateCreated = Convert.ToDateTime(dr["DateCreated"])
                        };
                        acList.Add(historyRecord);
                    }
                    return acList;
                }
                return null;
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }
    }
}
